#include <OpenCV/highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <iostream>
#include "../../BlobDetection/C++/BlobDetection.h"
#include "../../BlobDetection/C++/Blob.h"

//using namespace blobDetection;

const CFIndex CASCADE_NAME_LEN = 2048;
char    CASCADE_NAME[CASCADE_NAME_LEN] = "Shadow.jpg"; // this is a dummy

void blobsOnImage()
{
	CFBundleRef mainBundle  = CFBundleGetMainBundle ();
    assert (mainBundle);
    CFURLRef    cascade_url = CFBundleCopyResourceURL (mainBundle, CFSTR("Shadow"), CFSTR("jpg"), NULL);
    assert (cascade_url);
    Boolean     got_it      = CFURLGetFileSystemRepresentation (cascade_url, true, 
                                                                reinterpret_cast<UInt8 *>(CASCADE_NAME), CASCADE_NAME_LEN);
    if (! got_it)
        abort ();

	IplImage* img = cvLoadImage(CASCADE_NAME, 0);
	
	if (!img) {
		printf("Error loading image\n");
		exit (1);	
	}
	
	//cvSubRS(img,cvScalarAll(255),img);
	
	cvNamedWindow("Display", CV_WINDOW_AUTOSIZE);
	
	cvShowImage("Display", img);
	
	printf("Image ready to analysis\n");
	cvWaitKey();
	
	int *imageData = new int[img->width * img->height];
	
	blobDetection::BlobDetection theBlobDetection(img->width, img->height);
	theBlobDetection.setPosDiscrimination(false);
	theBlobDetection.setThreshold(0.38f);
	theBlobDetection.setBlobDimensionMin(5, 5);
	
	blobDetection::Blob b;
	b.setParent(&theBlobDetection);
	blobDetection::EdgeVertex eA,eB;
	
	// BGR
	printf("Image width: %d\n",img->width);
	printf("Image height: %d\n",img->height);
	printf("Image size: %d\n",img->imageSize);
	printf("Image width step: %d\n",img->widthStep);
	printf("Image size of pixel: %d\n", sizeof(img->imageData[0]));
	printf("Image nChannels: %d\n", img->nChannels);
	cvWaitKey();
	
	char* data = img->imageData;
	int x,y;

	for( y = 0; y < img->height; y++, data += img->widthStep )
		for( x = 0; x < img->width; x++ )
		{
			unsigned char r = data[x * img->nChannels+2];
			unsigned char g = data[x * img->nChannels+1];
			unsigned char b = data[x * img->nChannels];
			
			int rint = r;
			rint = (rint & 0x000000FF);
			
			int gint = g;
			gint = (gint & 0x000000FF) << 8;
		
			int bint = b;
			bint = (bint & 0x000000FF) << 16;
		
			imageData[x +y*img->width] = rint | gint | bint;
		
			//printf("RGB: %d %d %d %d\n", r, g, b, imageData[x +y*img->height]);
		
		}
	
	theBlobDetection.computeBlobs(imageData);
	printf("Blobs Count: %d\n",theBlobDetection.getBlobNb());
	for (int n=0 ; n<theBlobDetection.getBlobNb() ; n++)
	{
		b = theBlobDetection.getBlob(n);
		if (b.isOk())
		{
			for (int m=0;m<b.getEdgeNb();m++)
				{
					eA = b.getEdgeVertexA(m);
					eB = b.getEdgeVertexB(m);
					if (eA.isOk() && eB.isOk())
						 cvLine( img, cvPoint(eA.x*img->width, eA.y*img->height), cvPoint(eB.x*img->width, eB.y*img->height), CV_RGB(10, 100, 100), 1, CV_AA, 0 );
				}
			cvRectangle( img, cvPoint(b.xMin*img->width , b.yMin*img->height ), cvPoint ( b.xMax*img->width, b.yMax*img->height ), CV_RGB(255, 255, 0), 1, CV_AA, 0);
	
		}

	}
    cvShowImage("Display", img);
	
	printf("Image after blob detection\n");	
	cvWaitKey(0);
	
	exit (0);
};

void blobsOnCam()
{
	// create all necessary instances
    cvNamedWindow ("Blob", CV_WINDOW_AUTOSIZE);
    //CvCapture * camera = cvCreateCameraCapture (CV_CAP_ANY);
	CvCapture * camera = cvCaptureFromAVI("/Repositories/touchlib/tests/hard-5point.avi");

    // you do own an iSight, don't you ?!?
    if (! camera)
        abort ();

    // get an initial frame and duplicate it for later work
    IplImage *  img = cvQueryFrame (camera);
    
	int *imageData = new int[img->width * img->height];
		
	
	blobDetection::BlobDetection theBlobDetection(img->width, img->height);
	theBlobDetection.setPosDiscrimination(false);
	theBlobDetection.setThreshold(0.52f);
	theBlobDetection.setBlobDimensionMin(3,3);
	
	blobDetection::Blob b;
	b.setParent(&theBlobDetection);
	blobDetection::EdgeVertex eA,eB;
	// as long as there are images ...
    while (img = cvQueryFrame (camera))
    {

	char* data = img->imageData;
	int x,y;

	for( y = 0; y < img->height; y++, data += img->widthStep )
		for( x = 0; x < img->width; x++ )
		{
			unsigned char r = data[x * img->nChannels+2];
			unsigned char g = data[x * img->nChannels+1];
			unsigned char b = data[x * img->nChannels];
			
			int rint = r;
			rint = (rint & 0x000000FF);
			
			int gint = g;
			gint = (gint & 0x000000FF) << 8;
		
			int bint = b;
			bint = (bint & 0x000000FF) << 16;
		
			imageData[x +y*img->width] = rint | gint | bint;
		
			//printf("RGB: %d %d %d %d\n", r, g, b, imageData[x +y*img->height]);
		
		}
	
	theBlobDetection.computeBlobs(imageData);
	//printf("Blobs Count: %d\n",theBlobDetection.getBlobNb());
	for (int n=0 ; n<theBlobDetection.getBlobNb() ; n++)
	{
		b = theBlobDetection.getBlob(n);
		if (b.isOk())
		{

			for (int m=0;m<b.getEdgeNb();m++)
				{
					eA = b.getEdgeVertexA(m);
					eB = b.getEdgeVertexB(m);
					if (eA.isOk() && eB.isOk())
						 cvLine( img, cvPoint(eA.x*img->width, eA.y*img->height), cvPoint(eB.x*img->width, eB.y*img->height), CV_RGB(10, 100, 100), 1, CV_AA, 0 );
				}

			cvRectangle( img, cvPoint(b.xMin*img->width , b.yMin*img->height ), cvPoint ( b.xMax*img->width, b.yMax*img->height ), CV_RGB(255, 255, 0), 1, CV_AA, 0);


		}

      }

        cvShowImage ("Blob", img);
		
        // wait a tenth of a second for keypress and window drawing
        int key = cvWaitKey (100);
        if (key == 'q' || key == 'Q')
            break;
    }
	
	exit(0);

}

int main (int argc, char* argv[])
{
	bool imageBlob = false;
	
	if (imageBlob == true)
		blobsOnImage();
	else
		blobsOnCam();
		
	return 0;
}
